/* ===================

AX2E (AXESCON XACML 2.0 Engine) is the Java authorization engine, which implements OASIS XACML 2.0 standard.
Copyright (C) 2007 AXESCON LLC

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


Contact: AXESCON LLC - info{at}axescon.com

 =================== */
package axescon.xacml.xb.ctx;

import axescon.xacml.api.ExpressionEvalIndeterminateException;
import axescon.xacml.model.ctx.AttributeValue;
import axescon.xacml.model.policy.PolicyObject;
import axescon.xacml.model.shared.attr.*;
import org.apache.xmlbeans.XmlCursor;
import x0ContextSchemaOs.oasisNamesTcXacml2.AttributeValueType;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: argyn
 * Date: Jun 18, 2005
 * Time: 2:19:37 PM
 * To change this template use File | Settings | File Templates.
 */
public class XBAttrValueFactoryManager {

    public XBAttrValueFactoryManager() {
        this(true);
    }

    public XBAttrValueFactoryManager(boolean isSetDefaults) {
//        setClasses(new HashMap<String, XBAttributeValueFactory>());

        setFactories(new HashMap());
        if (isSetDefaults) setDefaults();
    }

    /**
     * @param fs Map<String, XBAttributeValueFactory>
     */
    public XBAttrValueFactoryManager(Map fs) {
        setFactories(fs);
    }

    public void setDefaults() {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();


        try {
            getFactories().put(AnyURIAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.AnyURIXBAttrValueFactory"));
            getFactories().put(Base64BinaryAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.Base64BinaryXBAttrValueFactory"));
            getFactories().put(BooleanAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.BooleanXBAttrValueFactory"));
            getFactories().put(DateAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.DateXBAttrValueFactory"));
            getFactories().put(DateTimeAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.DateTimeXBAttrValueFactory"));
            getFactories().put(DayTimeDurationAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.DayTimeDurationXBAttrValueFactory"));
            getFactories().put(DoubleAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.DoubleXBAttrValueFactory"));
            getFactories().put(HexBinaryAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.HexBinaryXBAttrValueFactory"));
            getFactories().put(IntegerAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.IntegerXBAttrValueFactory"));
            getFactories().put(RFC822NameAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.RFC822NameXBAttrValueFactory"));
            getFactories().put(StringAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.StringXBAttrValueFactory"));
            getFactories().put(TimeAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.TimeXBAttrValueFactory"));
            getFactories().put(X500NameAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.X500NameXBAttrValueFactory"));
            getFactories().put(YearMonthDurationAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.YearMonthDurationXBAttrValueFactory"));
            getFactories().put(IpAddressAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.IpAddressXBAttrValueFactory"));
            getFactories().put(DnsNameAttribute.dataType,
                    loadClass(cl, "axescon.xacml.xb.ctx.attr.factory.DnsNameXBAttrValueFactory"));
        } catch (Exception e) {
            // all standard classes should load
            throw new IllegalArgumentException(e.getMessage());
        }


    }


    public AttributeValue getAttributeValue(AttributeValueType vt, String type) {
        return getFactory(type).getAttributeValue(vt);
    }

    public axescon.xacml.model.policy.AttributeValue[] getAttributeValues(XmlCursor cur, String type)
            throws ExpressionEvalIndeterminateException {
        return getFactory(type).getAttributeValues(cur);
    }

    public axescon.xacml.model.policy.AttributeValue getAttributeValue(x0PolicySchemaOs.oasisNamesTcXacml2.AttributeValueType vt,
                                                              PolicyObject parent) {
        if (vt == null) return null;
        axescon.xacml.model.policy.AttributeValue ret = getFactory(vt.getDataType()).getAttributeValue(vt);
        ret.setParentPolicyObject(parent);
        return ret;
    }

/*
    public AttributeValue toAttributeValueType(AttributeValue v) {
        return getFactory(v.getType().toString()).toAttributeValueType(v);
    }
*/

    public void addFactory(String type, XBAttributeValueFactory f) {
        getFactories().put(type, f);
    }

    public void addFactory(String type, String className) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        getFactories().put(type, loadClass(cl, className));
    }

    XBAttributeValueFactory loadClass(ClassLoader cl, String className) {
        try {
            return (XBAttributeValueFactory) (cl.loadClass(className)).newInstance();
        } catch (Exception x) {
            throw new IllegalArgumentException(x.getMessage());
        }

    }

    /**
     * Map<String, XBAttributeValueFactory>
     */
    private Map factories;


    /**
     * @return Map<String, XBAttributeValueFactory>
     */
    public Map getFactories() {
        return factories;
    }

    /**
     * Map<String, XBAttributeValueFactory>
     *
     * @param factories
     */
    public void setFactories(Map factories) {
        this.factories = factories;
    }

    public XBAttributeValueFactory getFactory(String type) {
        XBAttributeValueFactory ret = (XBAttributeValueFactory) ((Map) getFactories()).get(type);
        if (ret == null) throw new RuntimeException("Unsupported type: " + type);
        return ret;
    }


}
